package com.alinesno.infra.smart.assistant.scene.scene.articleWriting.controller;

import cn.hutool.core.util.IdUtil;
import com.agentsflex.core.message.AiMessage;
import com.alinesno.infra.common.core.constants.SpringInstanceScope;
import com.alinesno.infra.common.extend.datasource.annotation.DataPermissionQuery;
import com.alinesno.infra.common.extend.datasource.annotation.DataPermissionSave;
import com.alinesno.infra.common.facade.datascope.PermissionQuery;
import com.alinesno.infra.common.facade.pageable.DatatablesPageBean;
import com.alinesno.infra.common.facade.response.AjaxResult;
import com.alinesno.infra.common.facade.response.R;
import com.alinesno.infra.common.web.adapter.login.account.CurrentAccountJwt;
import com.alinesno.infra.common.web.adapter.rest.BaseController;
import com.alinesno.infra.smart.assistant.adapter.SmartDocumentConsumer;
import com.alinesno.infra.smart.assistant.adapter.service.CloudStorageConsumer;
import com.alinesno.infra.smart.assistant.api.CodeContent;
import com.alinesno.infra.smart.assistant.api.IndustryRoleDto;
import com.alinesno.infra.smart.assistant.scene.common.utils.FileTool;
import com.alinesno.infra.smart.assistant.scene.scene.articleWriting.dto.*;
import com.alinesno.infra.smart.assistant.scene.scene.articleWriting.prompt.ArticlePromptHandle;
import com.alinesno.infra.smart.assistant.scene.scene.articleWriting.service.IArticleManagerService;
import com.alinesno.infra.smart.assistant.scene.scene.articleWriting.service.IArticleTemplateService;
import com.alinesno.infra.smart.assistant.scene.scene.articleWriting.service.IArticleWriterSceneService;
import com.alinesno.infra.smart.assistant.scene.scene.articleWriting.tools.ArticleChatRoleUtil;
import com.alinesno.infra.smart.assistant.scene.scene.articleWriting.tools.ExcelData;
import com.alinesno.infra.smart.assistant.scene.scene.articleWriting.tools.ExcelReaderUtil;
import com.alinesno.infra.smart.assistant.scene.scene.examPaper.dto.ExamPaperDTO;
import com.alinesno.infra.smart.assistant.service.IIndustryRoleService;
import com.alinesno.infra.smart.im.dto.FileAttachmentDto;
import com.alinesno.infra.smart.im.dto.MessageTaskInfo;
import com.alinesno.infra.smart.im.enums.TaskResultTypeEnums;
import com.alinesno.infra.smart.point.annotation.AgentPointAnnotation;
import com.alinesno.infra.smart.point.service.IAccountPointService;
import com.alinesno.infra.smart.scene.dto.SceneInfoDto;
import com.alinesno.infra.smart.scene.entity.ArticleGenerateSceneEntity;
import com.alinesno.infra.smart.scene.entity.ArticleManagerEntity;
import com.alinesno.infra.smart.scene.entity.ArticleTemplateEntity;
import com.alinesno.infra.smart.scene.entity.SceneEntity;
import com.alinesno.infra.smart.scene.enums.ExamQuestionTypeEnum;
import com.alinesno.infra.smart.scene.enums.SceneEnum;
import com.alinesno.infra.smart.scene.service.ISceneService;
import com.alinesno.infra.smart.utils.CodeBlockParser;
import com.alinesno.infra.smart.utils.RoleUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.http.util.Asserts;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;

/**
 * 处理与BusinessLogEntity相关的请求的Controller。
 * 继承自BaseController类并实现IBusinessLogService接口。
 *
 * @author luoxiaodong
 * @version 1.0.0
 */
@Slf4j
@RestController
@Scope(SpringInstanceScope.PROTOTYPE)
@RequestMapping("/api/infra/smart/assistant/scene/articleGenerate")
public class ArticleGeneratorSceneController extends BaseController<ArticleGenerateSceneEntity, IArticleWriterSceneService> {

    private final RestTemplate restTemplate = new RestTemplate();

    @Autowired
    private CloudStorageConsumer storageConsumer ;

    @Value("${alinesno.file.local.path:${java.io.tmpdir}}")
    private String localPath  ;

    @Autowired
    private CloudStorageConsumer cloudStorageConsumer ;

    @Autowired
    private SmartDocumentConsumer smartDocumentConsumer ;

    @Autowired
    private ISceneService sceneService;

    @Autowired
    private IArticleWriterSceneService service ;

    @Autowired
    private IArticleManagerService articleManagerSceneService;

    @Autowired
    private IArticleTemplateService articleTemplateService ;

    @Autowired
    private IIndustryRoleService roleService ;

    @Autowired
    private ArticleChatRoleUtil articleChatRoleUtil ;

    @Autowired
    private IAccountPointService accountPointService ;

    /**
     * 通过Id获取到场景
     *
     * @return
     */
    @DataPermissionQuery
    @GetMapping("/getScene")
    public AjaxResult getScene(Long id , PermissionQuery query) {

        SceneEntity entity = sceneService.getById(id);
        if (entity == null) {
            return AjaxResult.error("未找到对应的场景实体");
        }

        ArticleGenerateSceneDto dto = new ArticleGenerateSceneDto();
        BeanUtils.copyProperties(entity, dto);

        SceneInfoDto sceneInfoDto = SceneEnum.getSceneInfoByCode(entity.getSceneType());

        dto.setAgents(sceneInfoDto.getAgents());
        dto.setSceneId(sceneInfoDto.getId());

        ArticleGenerateSceneEntity examPagerSceneEntity = service.getBySceneId(id, query);
        if(examPagerSceneEntity != null){

            dto.setArticleWriterEngineer(examPagerSceneEntity.getArticleWriterEngineer());
            dto.setArticleWriterEngineerEntity(RoleUtils.getEditors(roleService , String.valueOf(examPagerSceneEntity.getArticleWriterEngineer())));

            dto.setArticleLayoutDesignerEngineer(examPagerSceneEntity.getArticleLayoutDesignerEngineer());
            dto.setArticleLayoutDesignerEngineerEntity(RoleUtils.getEditors(roleService , String.valueOf(examPagerSceneEntity.getArticleLayoutDesignerEngineer())));

        }

        return AjaxResult.success("操作成功.", dto);
    }

    /**
     * 导入数据
     *
     * @param file 导入文件
     */
    @PostMapping(value = "/uploadAttachment", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public AjaxResult sceneData(@RequestPart("file") MultipartFile file) throws Exception {

        // 新生成的文件名称
        String fileName = file.getOriginalFilename() ;
        String fileSuffix = Objects.requireNonNull(fileName).substring(fileName.lastIndexOf(".")+1);
        String newFileName = IdUtil.getSnowflakeNextId() + "." + fileSuffix;

        // 复制文件
        File targetFile = new File(localPath , newFileName);
        FileUtils.writeByteArrayToFile(targetFile, file.getBytes());

        log.debug("newFileName = {} , targetFile = {}" , newFileName , targetFile.getAbsoluteFile());

        R<String> r = storageConsumer.upload(targetFile) ;
        return AjaxResult.success("上传成功" , r.getData()) ;
    }

    /**
     * 聊天提示内容
     * @param dto
     * @param query
     * @return
     */
    @AgentPointAnnotation
    @DataPermissionQuery
    @PostMapping("/chatPromptContent")
    public DeferredResult<AjaxResult> chatPromptContent(@RequestBody @Validated ArticleGeneratorDTO dto, PermissionQuery query) {
        DeferredResult<AjaxResult> deferredResult = new DeferredResult<>(300_000L);

        deferredResult.onTimeout(() -> {
            deferredResult.setErrorResult(AjaxResult.error("请求超时"));
        });

        log.debug("dto = {}", dto);

        // 积分计数开始会话
        long currentAccountId = CurrentAccountJwt.getUserId() ;
        long accountOrgId = CurrentAccountJwt.get().getOrgId() ;

        try {
            ArticleGenerateSceneEntity entity = service.getBySceneId(dto.getSceneId(), query);
            Long articleWriterEngineer = entity.getArticleWriterEngineer();

            // 启动会话
            accountPointService.startSession(currentAccountId, accountOrgId , articleWriterEngineer);

            MessageTaskInfo taskInfo = dto.toPowerMessageTaskInfo();

            // 引用附件不为空，则引入和解析附件
            if(!CollectionUtils.isEmpty(dto.getAttachments())){
                List<FileAttachmentDto> attachmentList = cloudStorageConsumer.list(dto.getAttachments());
                taskInfo.setAttachments(attachmentList);
            }

            ArticleTemplateEntity templateEntity = null;
            if(dto.getSelectedTemplateId() != null){
                templateEntity = articleTemplateService.getById(dto.getSelectedTemplateId());
            }
            Asserts.notNull(templateEntity, "未找到对应的模板实体");

            String promptText = ArticlePromptHandle.generatorPrompt(dto, templateEntity);

            taskInfo.setRoleId(articleWriterEngineer);
            taskInfo.setChannelStreamId(dto.getChannelStreamId());
            taskInfo.setChannelId(dto.getSceneId());
            taskInfo.setSceneId(dto.getSceneId());
            taskInfo.setText(promptText);

            // 使用异步处理
            roleService.runRoleAgent(taskInfo).thenAccept(genContent -> {
                log.debug("genContent = {}", genContent.getGenContent());

                try {
                    // 获取文章内容并保存
                    String articleContent;
                    if(TaskResultTypeEnums.SUMMARY.getCode().equals(taskInfo.getResultType())){ // 总结性结果输出
                        articleContent = taskInfo.getFullContent();
                    } else {
                        List<CodeContent> contentList = CodeBlockParser.parseCodeBlocks(taskInfo.getFullContent());
                        articleContent = contentList.isEmpty() ? taskInfo.getFullContent() : contentList.get(0).getContent();
                    }

                    Long articleId = articleManagerSceneService.saveArticle(
                            articleContent,
                            dto,
                            entity,
                            query);

                    deferredResult.setResult(AjaxResult.success("操作成功", articleId));
                } catch (Exception e) {
                    log.error("Error processing article content", e);
                    deferredResult.setErrorResult(AjaxResult.error("处理文章内容时出错"));
                }
            }).whenComplete((result, ex) -> {
                // 积分计数结束会话
                accountPointService.endSession(currentAccountId , accountOrgId , taskInfo.getRoleId());
            }).exceptionally(ex -> {
                log.error("Error in role agent execution", ex);
                deferredResult.setErrorResult(AjaxResult.error("角色代理执行出错"));
                return null;
            });
        } catch (Exception e) {
            log.error("Error in chatPromptContent", e);
            deferredResult.setErrorResult(AjaxResult.error("处理请求时出错:" + e.getMessage()));
        }

        return deferredResult;
    }

    /**
     * 重新润色文章（异步高并发版）
     * @param dto 请求参数
     * @param query 权限查询条件
     * @return DeferredResult 异步响应结果
     */
    @AgentPointAnnotation
    @DataPermissionQuery
    @PostMapping("/reChatPromptContent")
    public DeferredResult<AjaxResult> reChatPromptContent(
            @RequestBody @Validated ReWriterArticleGeneratorDTO dto,
            PermissionQuery query) {

        // 1. 初始化DeferredResult，设置5分钟超时
        DeferredResult<AjaxResult> deferredResult = new DeferredResult<>(300_000L); // 5分钟=300秒

        // 超时回调处理
        deferredResult.onTimeout(() -> {
            log.warn("文章润色请求超时，articleId={}", dto.getArticleId());
            deferredResult.setErrorResult(AjaxResult.error("文章润色处理超时，请稍后重试"));
        });

        log.debug("dto = {}", dto);

        // 积分计数开始会话
        long currentAccountId = CurrentAccountJwt.getUserId() ;
        long accountOrgId = CurrentAccountJwt.get().getOrgId() ;

        try {
            // 2. 同步查询部分（快速操作）
            ArticleGenerateSceneEntity entity = service.getBySceneId(dto.getSceneId(), query);
            Long articleWriterEngineer = entity.getArticleWriterEngineer();

            // 启动会话
            accountPointService.startSession(currentAccountId, accountOrgId , articleWriterEngineer);

            ArticleManagerEntity articleManagerEntity = articleManagerSceneService.getById(dto.getArticleId());

            // 3. 构建任务信息
            MessageTaskInfo taskInfo = dto.toPowerMessageTaskInfo();
            String promptText = ArticlePromptHandle.generatorReWriterPrompt(dto, articleManagerEntity.getContent());

            taskInfo.setRoleId(articleWriterEngineer);
            taskInfo.setChannelStreamId(String.valueOf(dto.getChannelStreamId()));
            taskInfo.setChannelId(dto.getSceneId());
            taskInfo.setSceneId(dto.getSceneId());
            taskInfo.setText(promptText);

            // 4. 异步执行核心逻辑
            roleService.runRoleAgent(taskInfo)
                    .thenApplyAsync(genContent -> {
                        log.debug("润色结果生成完成，articleId={}", dto.getArticleId());

                        // 5. 结果解析（保持与原逻辑一致）
                        String articleContent = taskInfo.getFullContent();
                        List<CodeContent> contentList = CodeBlockParser.parseCodeBlocks(articleContent);

                        return contentList.isEmpty() ? articleContent : contentList.get(0).getContent();
                    })
                    .thenAccept(resultContent -> {
                        // 6. 成功响应
                        deferredResult.setResult(AjaxResult.success("操作成功", resultContent));
                    })
                    .whenComplete((result, ex) -> {
                        // 积分计数结束会话
                        accountPointService.endSession(currentAccountId , accountOrgId , taskInfo.getRoleId());
                    })
                    .exceptionally(ex -> {
                        // 7. 异常处理
                        log.error("文章润色失败，articleId={}", dto.getArticleId(), ex);
                        deferredResult.setErrorResult(AjaxResult.error("文章润色失败: " + ex.getMessage()));
                        return null;
                    });

        } catch (Exception e) {
            // 同步部分的异常捕获
            log.error("文章润色预处理失败", e);
            deferredResult.setErrorResult(AjaxResult.error("请求处理异常"));
        }

        return deferredResult;
    }

    /**
     * 重新润色文章
     * @param dto
     * @param query
     * @return
     */
    @DataPermissionQuery
    @PostMapping("/generateImages")
    public AjaxResult generateImages(@RequestBody @Validated ImageGeneratorDTO dto , PermissionQuery query) {

        ArticleGenerateSceneEntity entity = service.getBySceneId(dto.getSceneId(), query) ;
        Long articleWriterEngineer = entity.getArticleWriterEngineer() ;

        List<String> imageList = articleChatRoleUtil.generateImages(dto , articleWriterEngineer , query) ;

        return AjaxResult.success("操作成功" , imageList) ;
    }



    /**
     * 获取所有题型信息的Map列表
     */
    @GetMapping("/getQuestionTypes")
    public AjaxResult getQuestionTypes() {
        List<Map<String, Object>> questionTypes = ExamQuestionTypeEnum.getAllTypesList();
        return AjaxResult.success("操作成功", questionTypes);
    }

    /**
     * 获取所有题型信息的Map列表
     */
    @GetMapping("/getQuestionCategoryList")
    public AjaxResult getQuestionCategoryList() {
        List<Map<String, Object>> questionTypes = ExamQuestionTypeEnum.getCategoryList();
        return AjaxResult.success("操作成功", questionTypes);
    }

    /**
     * 保存试卷问题
     */
    @DataPermissionSave
    @PostMapping("/savePagerQuestion")
    public AjaxResult savePagerQuestion(@RequestBody @Validated ExamPaperDTO dto) {
        log.info("dto = {}" , dto);
        articleManagerSceneService.savePager(dto);  // 保存试卷
        return AjaxResult.success("操作成功") ;
    }

    /**
     * 更新试卷问题
     */
    @DataPermissionSave
    @PostMapping("/updatePagerQuestion")
    public AjaxResult updatePagerQuestion(@RequestBody @Validated ArticleGenerateSceneDto dto) {
        log.info("dto = {}" , dto);
        articleManagerSceneService.updatePager(dto);  // 删除试卷
        return AjaxResult.success("操作成功") ;
    }

    /**
     * 分页查询试题(pagerListByPage)
     */
    @DataPermissionQuery
    @PostMapping("/pagerListByPage")
    public AjaxResult pagerListByPage(DatatablesPageBean page, Long sceneId , PermissionQuery query) {
        List<ArticleManagerResponseDto> list = articleManagerSceneService.pagerListByPage(page, sceneId , query);
        return AjaxResult.success("操作成功." ,list);
    }

    /**
     * 获取试卷详情(getPagerDetail)
     */
    @GetMapping("/getPagerDetail")
    public AjaxResult getPagerDetail(Long id) {
        ArticleGenerateSceneDto entity = articleManagerSceneService.getPagerDetail(id);
        return AjaxResult.success("操作成功." ,entity);
    }

    /**
     * 通过id获取文章详情
     */
    @GetMapping("/getArticleById")
    public AjaxResult getArticleById(Long id) {
        ArticleManagerEntity entity = articleManagerSceneService.getById(id);
        return AjaxResult.success("操作成功." ,entity);
    }

    /**
     * 更新文章updateArticle
     */
    @DataPermissionSave
    @PostMapping("/updateArticle")
    public AjaxResult updateArticle(@RequestBody @Validated ArticleUpdateDto dto) {
        log.info("dto = {}" , dto);
        articleManagerSceneService.updateArticle(dto);  // 删除试卷
        return AjaxResult.success("操作成功") ;
    }

    /**
     * 文件上传
     * @return
     */
    @SneakyThrows
    @DataPermissionQuery
    @PostMapping("/importData")
    public AjaxResult importData(@RequestPart("file") MultipartFile file, String type , String updateSupport , PermissionQuery query){

        // 新生成的文件名称
        String fileSuffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf(".")+1);
        String newFileName = IdUtil.getSnowflakeNextId() + "." + fileSuffix;

        // 复制文件
        File targetFile = new File(localPath , newFileName);
        FileUtils.writeByteArrayToFile(targetFile, file.getBytes());

        log.debug("newFileName = {} , targetFile = {}" , newFileName , targetFile.getAbsoluteFile());

        List<ExcelData> dataList = ExcelReaderUtil.readExcel(targetFile.getAbsolutePath());
        for (ExcelData data : dataList) {
            log.debug("data = {}" , data);
        }

        Map<String, Object> failResult = articleTemplateService.readExcel(dataList , query) ;
        FileUtils.forceDeleteOnExit(targetFile);

        return AjaxResult.success("操作成功." , failResult);
    }

    /**
     * 与编辑角色沟通
     * @param dto
     * @return
     */
    @AgentPointAnnotation
    @DataPermissionQuery
    @PostMapping("/chatEditorRole")
    public DeferredResult<AjaxResult> chatEditorRole(@RequestBody @Validated ChatEditorDto dto, PermissionQuery query) {
        // 设置超时时间（毫秒），例如30秒
        DeferredResult<AjaxResult> deferredResult = new DeferredResult<>(120_000L);

        // 默认超时处理
        deferredResult.onTimeout(() ->
                deferredResult.setResult(AjaxResult.error("请求处理超时"))
        );

        // 错误处理
        deferredResult.onError((Throwable t) ->
                deferredResult.setResult(AjaxResult.error("处理请求时发生错误: " + t.getMessage()))
        );

        // 积分计数开始会话
        long currentAccountId = CurrentAccountJwt.getUserId() ;
        long accountOrgId = CurrentAccountJwt.get().getOrgId() ;

        ArticleGenerateSceneEntity entity = service.getBySceneId(dto.getSceneId(), query);
        Long articleWriterEngineer = entity.getArticleWriterEngineer();
        IndustryRoleDto roleDto = RoleUtils.getEditors(roleService, String.valueOf(articleWriterEngineer)).get(0);

        // 启动会话
        accountPointService.startSession(currentAccountId, accountOrgId , articleWriterEngineer);

        // 提交异步任务
        CompletableFuture<AiMessage> future = articleChatRoleUtil.chat(roleDto, dto, query);

        future.whenComplete((result, ex) -> {

            // 停止会话
            accountPointService.endSession(currentAccountId, accountOrgId , articleWriterEngineer);

            if (ex != null) {
                deferredResult.setErrorResult(AjaxResult.error("处理失败: " + ex.getMessage()));
            } else {
                deferredResult.setResult(AjaxResult.success("操作成功"));
            }
        });

        return deferredResult;
    }

    /**
     * 导出试卷为Word文档并直接下载
     * @param articleId 试卷ID
     * @param showAnswer 是否显示答案
     * @return ResponseEntity 包含Word文件流
     */
    @PostMapping("/export/{articleId}")
    public ResponseEntity<byte[]> exportPaperToWord(
            @PathVariable Long articleId,
            @RequestParam(required = false, defaultValue = "false") boolean showAnswer) {

        // 1. 验证试卷是否存在
        ArticleManagerEntity examPager = articleManagerSceneService.getById(articleId);
        if (examPager == null) {
            throw new RuntimeException("文章不存在，ID: " + articleId);
        }

        File tempFile = null;
        try {
            String title = String.valueOf(examPager.getId());

            tempFile = FileTool.createTempHtmlFile(examPager.getContent()) ;
            byte[] fileContent = smartDocumentConsumer.markdownToDocx(tempFile) ;

            // 使用RFC 5987标准编码文件名（支持中文和特殊字符）
            String fileName = title + ".docx";
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8)
                    .replace("+", "%20");

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

            // 关键设置：使用RFC 5987标准
            headers.add("Content-Disposition",
                    "attachment; filename=\"" + fileName + "\";" +
                            "filename*=UTF-8''" + encodedFileName);

            return ResponseEntity.ok()
                    .headers(headers)
                    .body(fileContent);

        } catch (IOException e) {
            log.error("导出试卷失败", e);
            throw new RuntimeException("导出试卷失败", e);
        } finally {
            // 5. 删除临时文件
            try {
                if(tempFile != null){
                    FileUtils.forceDeleteOnExit(tempFile) ;
                }
            } catch (IOException e) {
                log.error("删除临时文件失败", e);
            }
        }
    }

    /**
     * 通过id删除文章deleteArticle
     */
    @DeleteMapping("/deleteArticle")
    public AjaxResult deleteArticle(Long id) {
        articleManagerSceneService.removeById(id);
        return AjaxResult.success("操作成功") ;
    }

}